package org.xiaog.fastdao.util;

import org.xiaog.fastdao.annotation.*;

import java.lang.reflect.Method;
import java.util.Collection;

/**
 * @author xiaog
 */
public class SqlParser {

    private SqlType type;

    private String sql;

    private Object[] args;

    private boolean userMethod;
    private Class<?> returnType;

    public SqlParser(Method method) {
        Select select = method.getAnnotation(Select.class);
        if (select != null) {
            this.type = SqlType.SELECT;
            this.sql = select.value();
            return;
        }
        Update update = method.getAnnotation(Update.class);
        if (update != null) {
            this.type = SqlType.UPDATE;
            this.sql = update.value();
            return;
        }
        Insert insert = method.getAnnotation(Insert.class);
        if (insert != null) {
            this.type = SqlType.INSERT;
            this.sql = insert.value();
            return;
        }
        Delete delete = method.getAnnotation(Delete.class);
        if (delete != null) {
            this.type = SqlType.DELETE;
            this.sql = delete.value();
            return;
        }
    }

    public SqlParser() {}

    public SqlType getType() {
        return type;
    }

    public void setType(SqlType type) {
        this.type = type;
    }

    public String getSql() {
        return sql;
    }

    public void setSql(String sql) {
        this.sql = sql;
    }

    public Object[] getArgs() {
        return args;
    }

    public void setArgs(Object[] args) {
        this.args = args;
    }

    public Class<?> getReturnType() {
        return returnType;
    }

    public void setReturnType(Class<?> returnType) {
        this.returnType = returnType;
    }

    public boolean isUserMethod() {
        return userMethod;
    }

    public void setUserMethod(boolean userMethod) {
        this.userMethod = userMethod;
    }

    public static SqlParser getInstance(Method method, Class<?> eClass, Object[] args) {
        SqlParser parser = new SqlParser();
        EntityMeta meta = EntityMeta.getInstance(eClass);
        Class<?>[] paramsType = new Class[args.length];
        for (int i = 0; i < args.length; i++) {
            paramsType[i] = args[i].getClass();
        }
        if ("insert".equals(method.getName()) && paramsType.length == 1 && eClass == paramsType[0]) {
            parser.setType(SqlType.INSERT);
            SqlUtil.insert(parser,meta,args[0]);
        }else if ("updateById".equals(method.getName()) && paramsType.length == 1 && eClass == paramsType[0]) {
            parser.setType(SqlType.UPDATE);
            SqlUtil.updateById(parser,meta,args[0]);
        }else if ("deleteById".equals(method.getName()) && paramsType.length == 1 && meta.getIdType() == paramsType[0]) {
            parser.setType(SqlType.DELETE);
            parser.setArgs(args);
            parser.setSql(SqlUtil.getDeleteByIdSql(meta));
        }else if ("getById".equals(method.getName()) && paramsType.length == 1 && meta.getIdType() == paramsType[0]) {
            parser.setType(SqlType.SELECT);
            parser.setArgs(args);
            parser.setSql(SqlUtil.getGetByIdSql(meta));
            parser.setReturnType(eClass);
        }else if ("getByIds".equals(method.getName()) && paramsType.length == 1 && Collection.class.isAssignableFrom(paramsType[0])) {
            parser.setType(SqlType.SELECT);
            Collection<Object> ids = (Collection<Object>) args[0];
            parser.setArgs(ids.toArray());
            parser.setSql(SqlUtil.getGetByIdsSql(meta,ids.size()));
            parser.setReturnType(Collection.class);
        }else {
            parser = new SqlParser(method);
            parser.setArgs(args);
            parser.setUserMethod(true);
            parser.setReturnType(method.getReturnType());
        }
        return parser;
    }
}
